package com.wang.cloud.common.mysql;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.BaseBuilder;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.wang.cloud.common.mysql.domain.entity.BaseEntity;

import java.nio.file.Paths;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * mysql-代码生成器
 * 可以优化模板-增加crud接口
 *
 * @author wang ye
 * @date 2024/7/4
 */
public class FillCodeGenerator {
    private static final String[] tablePrefix = {"t_", "c_", "os_", "sys_", "t_base_", "base_"};
    public static void main(String[] args) {
        String url = "jdbc:mysql://127.0.0.1:3306/wang_mall?remarks=true&useInformationSchema=true";
        String username = "root";
        String password = "123456";
        FastAutoGenerator.create(url, username, password)
                // 全局配置
                .globalConfig((scanner, builder) -> builder.author("wy")
                                .outputDir(Paths.get(System.getProperty("user.dir")) + "/src/main/java") // 指定输出目录
                                .commentDate("yyyy-MM-dd")
                                .enableSpringdoc() // 开启springdoc，用于swagger3
                        //
                )
                .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                }))
                // 包配置
                .packageConfig((scanner, builder) ->
                        builder.parent("com.wang.cloud") // 设置父包名
                                .parent("com.wang.cloud")
                                .moduleName("manage")
                                .entity("domain.entity")
                                .mapper("mapper")
                                .service("service")
                                .serviceImpl("service.impl")
                                .xml("mapper.xml")
                                .pathInfo(Collections.singletonMap(OutputFile.xml, Paths.get(System.getProperty("user.dir")) + "/src/main/resources/mapper")) // 设置mapperXml生成路径
                )
                // 策略配置
                .strategyConfig((scanner, builder) -> {
                            builder.addInclude(getTables("sys_menu"));
//                            builder.addInclude(getTables("table_demo"));
                            controllerBuilder(builder);
                            entityBuilder(builder);
                            builder.mapperBuilder()
                                    .enableFileOverride()
                                    .enableBaseResultMap()
                                    .enableBaseColumnList();
                            builder.addTablePrefix(tablePrefix);
                            builder.build();

                        }
                )
                .injectionConfig(FillCodeGenerator::injectionConfig)
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    /**
     * 构建 Co、Vo实体类、转换器、feign Client和clientFallbackFactory
     *
     * @param consumer
     */
    private static void injectionConfig(InjectionConfig.Builder consumer) {
        // AddCo
        CustomFile addCo = new CustomFile.Builder()
                .fileName("AddCo.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
//                            .voTemplatePath("/templates/entityVo.java.ftl")
                .templatePath("/templates/entityAddCo.java.ftl")
                .enableFileOverride()
                .packageName("domain.co")
                .build();
        // UpdateCo
        CustomFile updateCo = new CustomFile.Builder()
                .fileName("UpdateCo.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", "")
                )
                .templatePath("/templates/entityUpdateCo.java.ftl")
                .enableFileOverride()
                .packageName("domain.co")
                .build();

        // PageCo
        CustomFile pageCo = new CustomFile.Builder()
                .fileName("PageCo.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
                .templatePath("templates/entityPageCo.java.ftl")
                .enableFileOverride()
                .packageName("domain.co")
                .build();
        // Vo
        CustomFile pageVo = new CustomFile.Builder()
                .fileName("PageVo.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
                .templatePath("/templates/entityPageVo.java.ftl")
                .enableFileOverride()
                .packageName("domain.vo")
                .build();

        // Vo
        CustomFile vo = new CustomFile.Builder()
                .fileName("Vo.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
                .templatePath("/templates/entityVo.java.ftl")
                .enableFileOverride()
                .packageName("domain.vo")
                .build();

        // AddCo
        CustomFile convertor = new CustomFile.Builder()
                .fileName("Convertor.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
//                            .voTemplatePath("/templates/entityVo.java.ftl")
                .templatePath("/templates/entityConvertor.java.ftl")
                .enableFileOverride()
                .packageName("convert")
                .build();

        // client
        CustomFile client = new CustomFile.Builder()
                .fileName("Client.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
                .templatePath("/templates/feign.java.ftl")
                .enableFileOverride()
                .packageName("client")
                .build();

        // clientFallbackFactory
        CustomFile clientFallbackFactory = new CustomFile.Builder()
                .fileName("ClientFallbackFactory.java")
                .formatNameFunction(tableInfo -> tableInfo.getEntityName()
                        .replace("Entity", ""))
                .templatePath("/templates/feignFallbackFactory.java.ftl")
                .enableFileOverride()
                .packageName("factory")
                .build();

        consumer.customFile(addCo);
        consumer.customFile(updateCo);
        consumer.customFile(pageCo);
        consumer.customFile(pageVo);
        consumer.customFile(vo);
        consumer.customFile(convertor);
        consumer.customFile(client);
        consumer.customFile(clientFallbackFactory);
    }

    // 处理 all 情况
    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

    /**
     * 构建--实体类
     *
     * @param builder
     * @return
     */
    public static BaseBuilder controllerBuilder(StrategyConfig.Builder builder) {
        return builder.controllerBuilder()
                .enableRestStyle()
                .enableFileOverride();
    }

    /**
     * 构建--实体类
     *
     * @param builder
     * @return
     */
    public static BaseBuilder entityBuilder(StrategyConfig.Builder builder) {
        return builder.entityBuilder()
                .enableLombok()
                .enableFileOverride()
                .enableTableFieldAnnotation()
                .disableSerialVersionUID()
                .superClass(BaseEntity.class)
                .idType(com.baomidou.mybatisplus.annotation.IdType.AUTO)
                // 格式化文件名称
                .formatFileName("%sEntity")
                // 添加表字段填充。 注这里有点问题，请检查实际是否生效
                .addTableFills(new Column("create_time", FieldFill.INSERT))
                .addTableFills(new Column("create_by", FieldFill.INSERT))
                .addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE))
                .addTableFills(new Column("update_by", FieldFill.INSERT_UPDATE))
                // 逻辑删除字段名(数据库)
                .logicDeleteColumnName("del_flag")
                // 逻辑删除属性名(实体)
                .logicDeletePropertyName("delFlag");
    }
}
